﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.RemoteTokenFactory
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IdentityModel.Claims;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using System.Xml;

namespace Microsoft.InfoCards
{
  internal class RemoteTokenFactory : TokenFactoryBase
  {
    internal const string MetadataExchangeClientKey = "MetadataExchangeClientKey";
    private ServiceEndpoint m_endPoint;
    private ChannelFactory<RemoteTokenFactory.ISts> m_channelFactory;
    private object m_channelChangeSync;
    private IWebProxy m_proxy;
    private ProtocolProfile m_protocolProfile;
    private Dictionary<string, bool> m_disclosedClaims;

    public RemoteTokenFactory(ServiceEndpoint endPoint, IWebProxy proxy)
    {
      this.m_endPoint = endPoint;
      this.m_channelChangeSync = new object();
      this.m_proxy = proxy;
    }

    protected override TokenDescriptor ProduceToken(
      InfoCard card,
      TokenCreationParameter parameter,
      TokenFactoryCredential credential,
      InfoCardPolicy policy,
      bool discloseOptional)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(null == card, nameof (card));
      InfoCardTrace.ThrowInvalidArgumentConditional(null == parameter, nameof (parameter));
      InfoCardTrace.ThrowInvalidArgumentConditional(null == credential, nameof (credential));
      InfoCardTrace.ThrowInvalidArgumentConditional(null == policy, nameof (policy));
      RSACryptoServiceProvider cryptoServiceProvider = (RSACryptoServiceProvider) null;
      byte[] numArray = (byte[]) null;
      SymmetricAlgorithm symmetricProof = (SymmetricAlgorithm) null;
      RSAKeyValue val = (RSAKeyValue) null;
      string internalTokenReference = string.Empty;
      string externalTokenReference = string.Empty;
      GenericXmlSecurityToken tok = (GenericXmlSecurityToken) null;
      this.m_protocolProfile = policy.ProtocolVersionProfile;
      bool flag1 = false;
      RSATokenProvider rsaTokenProvider = (RSATokenProvider) null;
      TokenDescriptor tokenDescriptor;
      try
      {
        if (SecurityKeyTypeInternal.AsymmetricKey == policy.KeyType)
        {
          cryptoServiceProvider = card.GetPublicCryptography(policy.Recipient.GetIdentifier());
          flag1 = true;
          InfoCardTrace.Assert(null == numArray, "Null in in asymmetric case");
        }
        else if (policy.KeyType == SecurityKeyTypeInternal.SymmetricKey)
        {
          numArray = new byte[(IntPtr) (policy.GetIntelligentKeySize(false) / 8U)];
          new RNGCryptoServiceProvider().GetNonZeroBytes(numArray);
          InfoCardTrace.Assert(null == cryptoServiceProvider, "Null in symmetric case");
        }
        else
        {
          InfoCardTrace.Assert(null == cryptoServiceProvider, "Null in no proof key case");
          InfoCardTrace.Assert(null == numArray, "Null in no proof key case");
          InfoCardTrace.Assert(SecurityKeyTypeInternal.NoKey == policy.KeyType, "Null in no proof key case");
        }
        if (this.m_endPoint == null)
          this.m_endPoint = RemoteTokenFactory.DoMexExchange(parameter, this.m_proxy);
        BindingElementCollection bindingElements = this.m_endPoint.Binding.CreateBindingElements();
        SecurityBindingElement securityBindingElement = bindingElements.Find<SecurityBindingElement>();
        if (securityBindingElement == null)
          throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("IndigoNoSuitableEndpointsForAddress", (object) this.m_endPoint.Address.Uri)));
        this.m_protocolProfile.WSTrust = securityBindingElement.MessageSecurityVersion.TrustVersion != TrustVersion.WSTrust13 ? (XmlNames.IWSTrust) XmlNames.WSTrustXmlSoap2005.Instance : (XmlNames.IWSTrust) XmlNames.WSTrustOasis2007.Instance;
        Binding binding1 = this.m_endPoint.Binding;
        EndpointAddress address = this.m_endPoint.Address;
        if (flag1)
        {
          SupportingTokenParameters supportingTokenParameters;
          if (securityBindingElement.OptionalOperationSupportingTokenParameters.ContainsKey(this.m_protocolProfile.WSTrust.RequestSecurityTokenAction))
          {
            supportingTokenParameters = securityBindingElement.OptionalOperationSupportingTokenParameters[this.m_protocolProfile.WSTrust.RequestSecurityTokenAction];
          }
          else
          {
            supportingTokenParameters = new SupportingTokenParameters();
            securityBindingElement.OptionalOperationSupportingTokenParameters[this.m_protocolProfile.WSTrust.RequestSecurityTokenAction] = supportingTokenParameters;
          }
          bool flag2 = true;
          foreach (SecurityTokenParameters securityTokenParameters in supportingTokenParameters.Endorsing)
          {
            if (securityTokenParameters is RsaSecurityTokenParameters)
            {
              flag2 = false;
              break;
            }
          }
          if (flag2)
          {
            RsaSecurityTokenParameters securityTokenParameters = new RsaSecurityTokenParameters();
            securityTokenParameters.InclusionMode = SecurityTokenInclusionMode.Never;
            securityTokenParameters.RequireDerivedKeys = false;
            supportingTokenParameters.Endorsing.Add((SecurityTokenParameters) securityTokenParameters);
          }
          binding1 = (Binding) new CustomBinding(bindingElements);
        }
        Binding binding2 = (Binding) new CustomBinding(Utility.UpdateProxyForHttpAndRestrictTransportBinding(binding1.CreateBindingElements(), this.m_proxy, false));
        InfoCardServiceClientCredentials clientCredentials1 = new InfoCardServiceClientCredentials(credential, this.m_protocolProfile);
        if (flag1)
        {
          rsaTokenProvider = new RSATokenProvider(policy, card);
          clientCredentials1.EndorsingSignatureTokenProvider = rsaTokenProvider;
        }
        ChannelFactory<RemoteTokenFactory.ISts> channelFactory = (ChannelFactory<RemoteTokenFactory.ISts>) null;
        bool flag3 = false;
        List<string> stringList;
        DisplayToken displayToken;
        try
        {
          InfoCardTrace.Assert(!flag3, "Will set to true upon sucess");
          lock (this.m_channelChangeSync)
          {
            if (this.IsAborted)
              throw InfoCardTrace.ThrowHelperError((Exception) new UserCancelledException());
            channelFactory = new ChannelFactory<RemoteTokenFactory.ISts>(binding2, address);
            clientCredentials1.Windows.AllowNtlm = false;
            ClientCredentials clientCredentials2 = channelFactory.Endpoint.Behaviors.Find<ClientCredentials>();
            if (clientCredentials2 != null)
              channelFactory.Endpoint.Behaviors.Remove((IEndpointBehavior) clientCredentials2);
            channelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
            channelFactory.Endpoint.Behaviors.Add((IEndpointBehavior) clientCredentials1);
            X509Certificate2Collection certificate2Collection = (X509Certificate2Collection) null;
            bool chainTrustPassed = false;
            switch (parameter.CredentialType)
            {
              case TokenFactoryCredentialType.UserNamePasswordCredential:
                clientCredentials1.UserName.UserName = ((UserNameTokenFactoryCredential) credential).UserName;
                clientCredentials1.UserName.Password = ((UserNameTokenFactoryCredential) credential).Password;
                certificate2Collection = this.GetCertificateChainFromAddress(address);
                InfoCardX509Validator.ValidateChainOrPeer(certificate2Collection[0], certificate2Collection, out chainTrustPassed);
                clientCredentials1.ServiceCertificate.DefaultCertificate = certificate2Collection[0];
                goto case TokenFactoryCredentialType.KerberosCredential;
              case TokenFactoryCredentialType.SelfIssuedCredential:
                clientCredentials1.IsSelfIssuedCred = true;
                SelfIssuedTokenFactoryCredential factoryCredential = (SelfIssuedTokenFactoryCredential) credential;
                clientCredentials1.SelectedCard = factoryCredential.LocalCard;
                certificate2Collection = this.GetCertificateChainFromAddress(address);
                X509Certificate2 x509Certificate2 = certificate2Collection[0];
                InfoCardX509Validator.ValidateChainOrPeer(x509Certificate2, certificate2Collection, out chainTrustPassed);
                Recipient.RecipientCertParameters recipientParams;
                string recipientIdHash = Recipient.CertGetRecipientIdHash(x509Certificate2, certificate2Collection, chainTrustPassed, out recipientParams);
                string organizationIdHash = Recipient.CertGetRecipientOrganizationIdHash(x509Certificate2, certificate2Collection, chainTrustPassed);
                this.EnsureSelfIssuedCardHasLedgerEntryForIssuer(factoryCredential.LocalCard, x509Certificate2, recipientIdHash, organizationIdHash, recipientParams, organizationIdHash);
                clientCredentials1.ServiceCertificate.DefaultCertificate = x509Certificate2;
                goto case TokenFactoryCredentialType.KerberosCredential;
              case TokenFactoryCredentialType.X509CertificateCredential:
                clientCredentials1.ClientCertificate.Certificate = ((X509CertificateTokenFactoryCredential) credential).Certificate;
                certificate2Collection = this.GetCertificateChainFromAddress(address);
                InfoCardX509Validator.ValidateChainOrPeer(certificate2Collection[0], certificate2Collection, out chainTrustPassed);
                clientCredentials1.ServiceCertificate.DefaultCertificate = certificate2Collection[0];
                goto case TokenFactoryCredentialType.KerberosCredential;
              case TokenFactoryCredentialType.KerberosCredential:
                clientCredentials1.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
                clientCredentials1.ServiceCertificate.Authentication.CustomCertificateValidator = InfoCardX509Validator.Create(certificate2Collection);
                this.m_channelFactory = channelFactory;
                break;
              default:
                InfoCardTrace.ThrowInvalidArgumentConditional(true, "CredentialType");
                goto case TokenFactoryCredentialType.KerberosCredential;
            }
          }
          try
          {
            RemoteTokenFactory.ISts channel = channelFactory.CreateChannel();
            if (cryptoServiceProvider != null)
              val = new RSAKeyValue((RSA) cryptoServiceProvider);
            this.m_disclosedClaims = card.GetClaimsToBeDisclosed(policy, discloseOptional);
            stringList = new List<string>(this.m_disclosedClaims.Count);
            stringList.AddRange((IEnumerable<string>) this.m_disclosedClaims.Keys);
            RequestSecurityToken rst = this.CreateRst(binding2.MessageVersion.Addressing, policy, card, discloseOptional, val, numArray, new CultureInfo(credential.LCID));
            Message message1 = Message.CreateMessage(binding2.MessageVersion, this.m_protocolProfile.WSTrust.RequestSecurityTokenAction, (BodyWriter) rst);
            Message message2 = (Message) null;
            if (XmlNames.WSSpecificationVersion.WSTrustXmlSoap2005 == this.m_protocolProfile.WSTrust.Version)
              message2 = channel.ProcessRequestSecurityTokenFeb2005(message1);
            else if (XmlNames.WSSpecificationVersion.WSTrustOasis2007 == this.m_protocolProfile.WSTrust.Version)
              message2 = channel.ProcessRequestSecurityTokenWSTrust13(message1);
            else
              InfoCardTrace.Assert(false, "Unsupported version of WS-Trust detected");
            WSIdentityFaultException.ThrowIfFaultMessage(message2, CultureInfo.GetCultureInfo(credential.LCID));
            if (policy.KeyType == SecurityKeyTypeInternal.SymmetricKey)
            {
              tok = RequestSecurityTokenResponseHelper.ProcessSymmetricTokenData(message2.GetReaderAtBodyContents(), (SecurityTokenSerializer) this.m_protocolProfile.TokenSerializer, (SecurityTokenResolver) null, numArray, this.m_protocolProfile, out displayToken);
              if (tok.ProofToken.SecurityKeys.Count < 1)
                throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("NoSymmetricKeyFound")));
              foreach (SecurityKey securityKey in tok.ProofToken.SecurityKeys)
              {
                if (securityKey is InMemorySymmetricSecurityKey)
                {
                  symmetricProof = (SymmetricAlgorithm) new RijndaelManaged();
                  symmetricProof.Key = ((SymmetricSecurityKey) securityKey).GetSymmetricKey();
                  break;
                }
              }
              if (symmetricProof == null)
                throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("NoSymmetricKeyFound")));
            }
            else if (SecurityKeyTypeInternal.AsymmetricKey == policy.KeyType)
            {
              tok = RequestSecurityTokenResponseHelper.ProcessAsymmetricTokenData(message2.GetReaderAtBodyContents(), (RSA) cryptoServiceProvider, (SecurityTokenSerializer) this.m_protocolProfile.TokenSerializer, (SecurityTokenResolver) null, this.m_protocolProfile, out displayToken);
            }
            else
            {
              InfoCardTrace.Assert(SecurityKeyTypeInternal.NoKey == policy.KeyType, "Bad enum member for SecurityKeyTypeInternal");
              tok = RequestSecurityTokenResponseHelper.ProcessBearerTokenData(message2.GetReaderAtBodyContents(), (SecurityTokenSerializer) this.m_protocolProfile.TokenSerializer, (SecurityTokenResolver) null, this.m_protocolProfile, out displayToken);
            }
            channelFactory.Close();
            flag3 = true;
          }
          finally
          {
            lock (this.m_channelChangeSync)
            {
              if (!flag3)
                channelFactory.Abort();
              this.m_channelFactory = (ChannelFactory<RemoteTokenFactory.ISts>) null;
            }
          }
        }
        catch (EndpointNotFoundException ex)
        {
          throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("EndpointNotFound"), (Exception) ex));
        }
        catch (InfoCardBaseException ex)
        {
          throw;
        }
        catch (Exception ex)
        {
          if (!InfoCardTrace.IsFatal(ex))
            throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("ProblemRetrievingTokenFromIdentityProvider"), ex));
          throw;
        }
        XmlElement xmlElement = tok.TokenXml;
        X509RecipientIdentity immediateTokenRecipient = policy.ImmediateTokenRecipient as X509RecipientIdentity;
        if (immediateTokenRecipient != null && !this.IsEncryptedXml(xmlElement))
        {
          if (AppliesToBehaviorDecisionTable.GetAppliesToBehaviorDecisionForRst(policy, card.RequireAppliesto) == AppliesToBehaviorDecision.DoNotSend)
          {
            try
            {
              string asymmetricKeyWrapAlgorithm = policy.KeyType != SecurityKeyTypeInternal.SymmetricKey ? (SecurityKeyTypeInternal.AsymmetricKey != policy.KeyType ? SecurityAlgorithmSuite.Default.DefaultAsymmetricKeyWrapAlgorithm : (!string.IsNullOrEmpty(policy.OptionalRstParams.EncryptWith) ? policy.OptionalRstParams.EncryptWith : SecurityAlgorithmSuite.Default.DefaultAsymmetricKeyWrapAlgorithm)) : SecurityAlgorithmSuite.Default.DefaultAsymmetricKeyWrapAlgorithm;
              xmlElement = EncryptionUtility.EncryptSecurityToken(xmlElement, immediateTokenRecipient.LeafCertificate, !string.IsNullOrEmpty(policy.OptionalRstParams.EncryptionAlgorithm) ? policy.OptionalRstParams.EncryptionAlgorithm : SecurityAlgorithmSuite.Default.DefaultEncryptionAlgorithm, asymmetricKeyWrapAlgorithm, policy.ProtocolVersionProfile);
            }
            catch (Exception ex)
            {
              if (!InfoCardTrace.IsFatal(ex))
                throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException("ServiceTokenEncryptionFailed", ex));
              throw;
            }
          }
        }
        this.GetKeyIdentifierClauses(tok, policy.ProtocolVersionProfile, out internalTokenReference, out externalTokenReference);
        this.FillOutDisplayToken(card, displayToken);
        tokenDescriptor = new TokenDescriptor(tok.Id, tok.ValidFrom, tok.ValidTo, xmlElement, displayToken, symmetricProof, internalTokenReference, externalTokenReference, (IEnumerable<string>) stringList);
        symmetricProof = (SymmetricAlgorithm) null;
      }
      finally
      {
        ((IDisposable) cryptoServiceProvider)?.Dispose();
        if (val != null)
        {
          ((IDisposable) val.Key).Dispose();
          val.Key = (RSA) null;
        }
        ((IDisposable) symmetricProof)?.Dispose();
        rsaTokenProvider?.Dispose();
      }
      return tokenDescriptor;
    }

    protected override void OnAbort()
    {
      lock (this.m_channelChangeSync)
      {
        if (this.IsAborted || this.m_channelFactory == null)
          return;
        this.m_channelFactory.Abort();
      }
    }

    private X509Certificate2Collection GetCertificateChainFromAddress(
      EndpointAddress address)
    {
      if ((EndpointAddress) null == address || address.Identity == null)
        throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("NoCertificateInEndPoint")));
      X509CertificateEndpointIdentity identity = address.Identity as X509CertificateEndpointIdentity;
      if (identity == null || identity.Certificates == null || identity.Certificates.Count < 1)
        throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("NoCertificateInEndPoint")));
      return identity.Certificates;
    }

    public static ServiceEndpoint DoMexExchange(
      TokenCreationParameter param,
      IWebProxy proxy)
    {
      ServiceEndpoint endPoint = (ServiceEndpoint) null;
      bool flag = false;
      if (param == null || (EndpointAddress) null == param.Epr)
        throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("InvalidServiceUri")));
      EndpointAddress address = Utility.DeriveMexAddress(param.Epr);
      if ((EndpointAddress) null == address)
        throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("InvalidServiceUri")));
      InfoCardMetadataExchangeClient metadataExchangeClient = new InfoCardMetadataExchangeClient();
      metadataExchangeClient.Proxy = proxy;
      MetadataSet metadata = (MetadataSet) null;
      metadataExchangeClient.ResolveMetadataReferences = true;
      metadataExchangeClient.MaximumResolvedReferences = InfoCardConstants.MaximumMexChainLength;
      Exception inner = (Exception) null;
      try
      {
        metadata = metadataExchangeClient.GetMetadata(address);
        flag = true;
      }
      catch (Exception ex)
      {
        if (InfoCardTrace.IsFatal(ex))
          throw;
      }
      if (!flag)
      {
        try
        {
          metadata = metadataExchangeClient.GetMetadata(address.Uri, MetadataExchangeClientMode.HttpGet);
          flag = true;
        }
        catch (Exception ex)
        {
          if (InfoCardTrace.IsFatal(ex))
            throw;
          else
            inner = ex;
        }
      }
      if (!flag)
        throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("EndpointNotFound"), inner));
      WsdlImporter wsdlImporter = new WsdlImporter(metadata);
      wsdlImporter.State.Add((object) "MetadataExchangeClientKey", (object) metadataExchangeClient);
      ServiceEndpointCollection endpointCollection = wsdlImporter.ImportAllEndpoints();
      if (endpointCollection != null)
      {
        foreach (ServiceEndpoint serviceEndpoint in (Collection<ServiceEndpoint>) endpointCollection)
        {
          if (Utility.CompareUri(serviceEndpoint.Address.Uri, param.Epr.Uri))
          {
            ISecurityCapabilities property = serviceEndpoint.Binding.GetProperty<ISecurityCapabilities>(new BindingParameterCollection());
            if (property != null && property.SupportedRequestProtectionLevel == ProtectionLevel.EncryptAndSign && (property.SupportedResponseProtectionLevel == ProtectionLevel.EncryptAndSign && property.SupportsServerAuthentication))
            {
              endPoint = serviceEndpoint;
              break;
            }
          }
        }
        if (endPoint == null)
          throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("IndigoNoSuitableEndpointsForAddress", (object) param.Epr.Uri.AbsoluteUri)));
        RemoteTokenFactory.ValidateEndpointAddressIdentityFromMex(endPoint);
        return endPoint;
      }
      throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("IndigoNoSuitableEndpointsForAddress", (object) param.Epr.Uri.AbsoluteUri)));
    }

    private static void ValidateEndpointAddressIdentityFromMex(ServiceEndpoint endPoint)
    {
      EndpointIdentity identity = endPoint.Address.Identity;
      Uri uri = endPoint.Address.Uri;
      if (identity != null && identity.IdentityClaim != null && (identity.IdentityClaim.ClaimType != null && ClaimTypes.Dns != identity.IdentityClaim.ClaimType) && (ClaimTypes.Spn != identity.IdentityClaim.ClaimType && ClaimTypes.Thumbprint != identity.IdentityClaim.ClaimType))
        throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("IndigoNoSuitableEndpointsForAddress", (object) endPoint.Address.Uri)));
      if (identity == null || identity.IdentityClaim == null || identity.IdentityClaim.ClaimType == null)
        return;
      if (ClaimTypes.Dns == identity.IdentityClaim.ClaimType)
      {
        if (!NativeMcppMethods.DnsNameCompareWrapper(identity.IdentityClaim.Resource.ToString(), uri.DnsSafeHost))
          throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("IndigoNoSuitableEndpointsForAddress", (object) endPoint.Address.Uri)));
      }
      else if (ClaimTypes.Spn == identity.IdentityClaim.ClaimType)
      {
        string str = identity.IdentityClaim.Resource.ToString();
        if (!string.Format((IFormatProvider) CultureInfo.InvariantCulture, "host/{0}", (object) uri.DnsSafeHost).Equals(str, StringComparison.OrdinalIgnoreCase))
          throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("IndigoNoSuitableEndpointsForAddress", (object) endPoint.Address.Uri)));
      }
      else
        InfoCardTrace.Assert(ClaimTypes.Thumbprint == identity.IdentityClaim.ClaimType, "Should be Thumbprint");
    }

    private RequestSecurityToken CreateRst(
      AddressingVersion version,
      InfoCardPolicy policy,
      InfoCard card,
      bool discloseOptional,
      RSAKeyValue val,
      byte[] clientEntropyForSymmetric,
      CultureInfo displayCulture)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(null == policy, nameof (policy));
      InfoCardTrace.ThrowInvalidArgumentConditional(null == card, nameof (card));
      return (RequestSecurityToken) new RequestSecurityTokenForRemoteTokenFactory(new RequestSecurityTokenParameters(version, card, policy, discloseOptional, val, this.m_disclosedClaims, "ProcessRequestSecurityToken", clientEntropyForSymmetric, displayCulture));
    }

    private void GetKeyIdentifierClauses(
      GenericXmlSecurityToken tok,
      ProtocolProfile profile,
      out string internalTokenReference,
      out string externalTokenReference)
    {
      if (tok.InternalTokenReference != null)
      {
        if (tok.ExternalTokenReference != null)
        {
          try
          {
            using (StringWriter stringWriter = new StringWriter((IFormatProvider) CultureInfo.InvariantCulture))
            {
              profile.TokenSerializer.WriteKeyIdentifierClause((XmlWriter) XmlDictionaryWriter.CreateDictionaryWriter((XmlWriter) new XmlTextWriter((TextWriter) stringWriter)), tok.InternalTokenReference);
              stringWriter.Flush();
              internalTokenReference = stringWriter.GetStringBuilder().ToString();
            }
            using (StringWriter stringWriter = new StringWriter((IFormatProvider) CultureInfo.InvariantCulture))
            {
              profile.TokenSerializer.WriteKeyIdentifierClause((XmlWriter) XmlDictionaryWriter.CreateDictionaryWriter((XmlWriter) new XmlTextWriter((TextWriter) stringWriter)), tok.ExternalTokenReference);
              stringWriter.Flush();
              externalTokenReference = stringWriter.GetStringBuilder().ToString();
              return;
            }
          }
          catch (XmlException ex)
          {
            throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("IPSTSClientInvalidTokenReference"), (Exception) ex));
          }
        }
      }
      throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("IPSTSClientInvalidTokenReference")));
    }

    private void EnsureSelfIssuedCardHasLedgerEntryForIssuer(
      InfoCard card,
      X509Certificate2 issuerCert,
      string recipientId,
      string recipientOrgId,
      Recipient.RecipientCertParameters recipientParams,
      string immediateTokenRecipientOrganizationIdentifier)
    {
      LedgerEntryCollection ledger = card.GetLedger();
      StoreConnection connection = StoreConnection.GetConnection();
      try
      {
        ledger.Get(connection);
        if (!ledger.ContainsKey(recipientId))
        {
          connection.BeginTransaction();
          try
          {
            InfoCardMasterKey masterKey = card.GetMasterKey(connection);
            if (card.IsPinProtected)
            {
              InfoCardTrace.Assert(!string.IsNullOrEmpty(card.Pin), "Should not be null here");
              masterKey.Decrypt(masterKey.GetPinHelper(card.Pin));
            }
            Recipient recipient = new Recipient(issuerCert, recipientId, recipientOrgId, false, 0U, recipientParams);
            recipient.Save(connection);
            LedgerEntry entry = LedgerEntry.NewLedgerEntry(card.Id, recipient, card.Key, immediateTokenRecipientOrganizationIdentifier);
            ledger.Add(entry);
            entry.Save(connection);
            connection.CommitTransaction();
          }
          catch
          {
            connection.RollbackTransaction();
            throw;
          }
        }
        else
          InfoCardTrace.Assert(immediateTokenRecipientOrganizationIdentifier == recipientOrgId, "For the self issued case the RP should be same as token recipient");
      }
      finally
      {
        connection.Close();
      }
    }

    private void FillOutDisplayToken(InfoCard card, DisplayToken displayToken)
    {
      if (displayToken.ClaimList == null)
        return;
      InfoCardClaimCollection claims = card.GetClaims();
      foreach (DisplayClaim claim in displayToken.ClaimList)
      {
        if (string.IsNullOrEmpty(claim.Name))
        {
          string str = (string) null;
          string id = claim.Id;
          if (!string.IsNullOrEmpty(claim.Id))
          {
            if (claims.ContainsKey(id))
              str = claims[id].DisplayTag;
            if (string.IsNullOrEmpty(str))
              str = id;
          }
          else
            str = SR.GetString("ServiceDisplayTokenNoClaimName");
          claim.Name = str;
        }
      }
    }

    private bool IsEncryptedXml(XmlElement content)
    {
      if ("EncryptedData" == content.LocalName)
        return "http://www.w3.org/2001/04/xmlenc#" == content.NamespaceURI;
      return false;
    }

    [ServiceContract(Name = "RequestBrowserToken", Namespace = "http://schemas.xmlsoap.org/ws/2005/05/identity")]
    internal interface ISts
    {
      [OperationContract(Action = "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue", Name = "ProcessRequestSecurityTokenFeb2005", ProtectionLevel = ProtectionLevel.EncryptAndSign, ReplyAction = "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue")]
      Message ProcessRequestSecurityTokenFeb2005(Message rstMessage);

      [OperationContract(Action = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue", Name = "ProcessRequestSecurityTokenWSTrust13", ProtectionLevel = ProtectionLevel.EncryptAndSign, ReplyAction = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTRC/IssueFinal")]
      Message ProcessRequestSecurityTokenWSTrust13(Message rstMessage);
    }
  }
}
